import string
from BigPrize.GameRule.Math import Math
from BigPrize.models import UserWin, Draw, UserVote, VlUser

__author__ = 'zhouqi'

class BigPrize(object):
    """
    this class afford count chance, transfer with db store format and view format, compute one draw all tickets prize

    compute one draw all tickets prize logic:
    1. get all ticket
    2. for each ticket
    3. compute win set
    4. add prz record to list
    """

    @classmethod
    def ComputeDrawPrz(cls, result, przLevels, userVotes):
        wins = []
        for eachVote in userVotes:
            for przLvl, winChance, przAmt in BigPrize.ComputeWinSet(BigPrize.GetRightNum(eachVote.content, result),
                                                                    przLevels):
                win = UserWin()
                win.voteId = UserVote(eachVote.voteId)
                win.drawId = eachVote.drawId
                win.userId = eachVote.userId
                win.chance = eachVote.chance
                win.time = eachVote.time
                win.multiple = eachVote.multiple
                win.content = eachVote.content
                win.przLvl = przLvl
                win.winChance = winChance
                win.prize = przAmt
                win.winId = str(win.voteId.voteId) + '_' + str(win.przLvl)
                wins.append(win)
        return wins

    @classmethod
    def GetRightNum(cls, dbContent, result):
        """
        compute vote content has how many right num
        """
        resultArray = string.split(result, chr(127))
        contentArray = string.split(dbContent, chr(127))
        if len(contentArray) == 2:
            a = BigPrize.Find(contentArray[0], resultArray[0])
            b = BigPrize.Find(contentArray[1], resultArray[1])
            return  [len(a), len(b), len(contentArray[0]) - len(a), len(contentArray[1]) - len(b)]
        elif len(contentArray) == 4:
            a = BigPrize.Find(contentArray[0], resultArray[0])
            b = BigPrize.Find(contentArray[1], resultArray[1])
            c = BigPrize.Find(contentArray[2], resultArray[0])
            d = BigPrize.Find(contentArray[3], resultArray[1])
            return  [len(a), len(b), len(contentArray[0]) - len(a), len(contentArray[1]) - len(b)
                , len(c), len(d), len(contentArray[2]) - len(c), len(contentArray[3]) - len(d)]
        else:
            raise Exception


    @classmethod
    def ComputeWinSet(cls, rightNum, przLevels):
        """
        compute all win set condition.
        przLevels should be a list that set up like format { przLvl : oneChancePrz, przLvl : oneChancePrz}
        it will return a list that set up like format [(przLvl, winChance, przAmt), (przLvl, winChance, przAmt)]
        to do : remember cache!
        """
        winSets = []
        przRule = {1: [5, 2], 2: [5, 1], 3: [5, 0], 4: [4, 2], 5: [4, 1], 6: [4, 0, 3, 2], 7: [3, 1, 2, 2],
                   8: [3, 0, 1, 2, 2, 1, 0, 2]}
        winChance = 0
        if len(rightNum) == 4:
            for prz in range(1, 9):
                winChance = 0
                for i in range(len(przRule[prz]) / 2):
                    winChance = winChance + Math.Combination(przRule[prz][i * 2], rightNum[0])\
                                            * Math.Combination(5 - przRule[prz][i * 2], rightNum[2])\
                                            * Math.Combination(przRule[prz][i * 2 + 1], rightNum[1])\
                    * Math.Combination(2 - przRule[prz][i * 2 + 1], rightNum[3])
                if winChance > 0:
                    winSets.append([prz, winChance, przLevels[prz]])

        if len(rightNum) == 8:
            for prz in range(1, 9):
                winChance = 0
                for i in range(len(przRule[prz]) / 2):
                    winChance = winChance + Math.Combination(przRule[prz][i * 2] - rightNum[4], rightNum[0])\
                                            * Math.Combination(5 - przRule[prz][i * 2] - rightNum[6], rightNum[2])\
                                            * Math.Combination(przRule[prz][i * 2 + 1] - rightNum[5], rightNum[1])\
                    * Math.Combination(2 - przRule[prz][i * 2 + 1] - rightNum[7], rightNum[3])
                if winChance > 0:
                    winSets.append([prz, winChance, przLevels[prz]])
        return winSets

    @classmethod
    def Find(cls, array, source):
        """
        compare array with source, check that array has how many item in source.
        it should bu used for compute prize
        """
        return [each for each in array if each in source]

    @classmethod
    def Count(cls, dbContent):
        """
        count vote content have how many chance.
        content should be db store format.
        """
        array = string.split(dbContent, chr(127))
        if len(array) == 2:
            return Math.Combination(5, len(array[0])) * Math.Combination(2, len(array[1]))
        elif len(array) == 4:
            return Math.Combination(5 - len(array[2]), len(array[0])) * Math.Combination(2 - len(array[3]),
                                                                                         len(array[1]))
        else:
            raise Exception

    @classmethod
    def Encode(cls, viewContent):
        """
        encode content from view format to db store format
        """
        array = string.split(viewContent, ':')
        return string.join([BigPrize.__Encode(string.split(each, ',')) for each in array], chr(127))

    @classmethod
    def __Encode(cls, array):
        """
        private method for encode
        """
        if len(array) > 0 and len(array[0]) > 0:
            return string.join(map(chr, map(int, array)), '')
        else:
            return ''

    @classmethod
    def Decode(cls, dbContent):
        array = string.split(dbContent, chr(127))
        #return string.join([BigPrize.__Decode(each) for each in array], ":")
        return string.join([string.join([str(ord(each)) for each in eachArray], ',') for eachArray in array], ":")
